import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
import java.util.Random;


// Represente un rectangle compose des carres qui ne peuvent contenir qu'un seul animal
public class Grille { 
	private int hauteur,largeur;
	private Animal[][] animaux;
  private Herbe [][] herbe;
	private static final Random rand = Randomizer.getRandom();
	
  
	public Grille(int hauteur,int largeur){
		this.hauteur=hauteur;
		this.largeur=largeur;
		animaux=new Animal[hauteur][largeur];
    herbe = new Herbe[hauteur][largeur];
    for(int i = 0; i < getHauteur(); i++) {
        for(int j = 0; j < getLargeur(); j++) {
            herbe[i][j] = new Herbe();
        }
    }
	}
  
  // Efface tous les animaux
	public void clear(){
		for(int i = 0; i < hauteur; i++) {
            for(int j = 0; j < largeur; j++) {
                animaux[i][j] = null;
            }
        } 
	}
   
  
	// Efface un objet sur une position specifique
  public void clear(Position p){
        animaux[p.getLigne()][p.getCol()] = null;
    }
	
  // Met un animal sur la grille
	public void place(Animal animal, Position p){
        animaux[p.getLigne()][p.getCol()] = animal;
    }
	
	public Object getObjectAt(int ligne, int col){
        return animaux[ligne][col];
    }
    
    //@return Un objet sur la grille s'il y en a, null sinon
    public Object getObjectAt(Position position){
        return getObjectAt(position.getLigne(), position.getCol());
    }
    
    //@return L'herbe sur la grille s'il y en a, null sinon
    public Herbe getHerbeAt(Position position){
        return getHerbeAt(position.getLigne(), position.getCol());
    }
    
    //@return Position de l'herbe sur une case voulue
    public Herbe getHerbeAt(int ligne, int col){
        return herbe[ligne][col];
    }
        
    //@return Faux si la position en parametre est occupee par un objet
    public boolean estPositionVide(Position pos){
    	if (animaux.length==0) return false;
    	if (getObjectAt(pos)==null)return true;
    	else return false;
    }
 	
 	

    //@return Une position adjacente valide
    public Position positionAdjacenteRandom(Position position){
        List<Position> adjacent = positionsAdjacentes(position);
        return adjacent.get(0);
    }
   
    //@return Une liste shuffled de positions adjacentes disponible
    public List<Position> positionsAdjacentesDispos(Position position){
        List<Position> dispo = new LinkedList<Position>();
        List<Position> adjacent = positionsAdjacentes(position);
        for(Position next : adjacent) {
            if(getObjectAt(next) == null) {
                dispo.add(next);
            }
        }
        return dispo;
    } 
    
    //@return Position adjacente disponible, sinon null
    public Position positionAdjacDispo(Position position){
        List<Position> dispo = positionsAdjacentesDispos(position);
        if(dispo.size() > 0) {
            return dispo.get(0);
        }
        else {
            return null;
        }
    }


    //@return Une liste shuffled de positions valides adjacentes
    public List<Position> positionsAdjacentes(Position position){
        assert position != null : "Il y a une position nulle";
        List<Position> positions = new LinkedList<Position>();
        if(position != null) {
            int ligne = position.getLigne();
            int col = position.getCol();
            for(int i = -1; i <= 1; i++) {
                int nextLigne = ligne + i;
                if(nextLigne >= 0 && nextLigne < hauteur) {
                    for(int j = -1; j <= 1; j++) {
                        int nextCol = col + j;
                        // Exclut les positions non valides et la position originale.
                        if(nextCol >= 0 && nextCol < largeur && (i != 0 || j != 0)) {
                            positions.add(new Position(nextLigne, nextCol));
                        }
                    }
                }
            }
            Collections.shuffle(positions, rand);//melanger la liste
        }
        return positions;
    }
    
    public int getHauteur(){
        return this.hauteur;
    }
   
    public int getLargeur(){
        return largeur;
    }
    
    public Animal[][] getAnimaux(){
    	return animaux;
    }
//    public String toString(){
//    	String resultat="";
//    	String objet="";
//    	String cellule="";
//    	String ligne="";
//    	Object a;
//    	for(int i=0;i<hauteur;i++){
//    		for(int j=0;j<largeur;j++){
//    			a=getObjectAt(i, j);
//    			if (a==null||!(a instanceof Animal)){
//    				objet="  ";
//    			}
//    			else{
//    				if (a instanceof Loup) objet="L";
//    				else objet = "M";
//    			}
//    			cellule+="+--\n|"+objet;
//    			ligne+=cellule;
//    			System.out.println(ligne);
//    		}
////    		resultat+="|\n";
//    	}
//    	return resultat;
//    }
       
      
	
	

}
